home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / autoconf.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  11KB  |  481 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * AutoConfig devices
  5.   *
  6.   * Copyright 1995, 1996 Bernd Schmidt
  7.   * Copyright 1996 Ed Hanway
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12.  
  13. #include "config.h"
  14. #include "options.h"
  15. #include "machdep/m68k.h"
  16. #include "uae.h"
  17. #include "memory.h"
  18. #include "custom.h"
  19. #include "readcpu.h"
  20. #include "newcpu.h"
  21. #include "compiler.h"
  22. #include "autoconf.h"
  23. #include "osdep/exectasks.h"
  24.  
  25. /* We'll need a lot of these. */
  26. #define MAX_TRAPS 4096
  27. static TrapFunction traps[MAX_TRAPS];
  28. static int trapmode[MAX_TRAPS];
  29. static const char *trapstr[MAX_TRAPS];
  30. static uaecptr trapoldfunc[MAX_TRAPS];
  31.  
  32. static int max_trap = 0;
  33. int lasttrap;
  34.  
  35. /* Stack management */
  36.  
  37. /* The mechanism for doing m68k calls from native code is as follows:
  38.  *
  39.  * m68k code executes, stack is main
  40.  * calltrap to execute_fn_on_extra_stack. new stack is allocated
  41.  * do_stack_magic is called for the first time
  42.  * current context is saved with setjmp [0]
  43.  *  transfer_control is done
  44.  *   native code executes on new stack
  45.  *   native code calls call_m68k
  46.  *   setjmp saves current context [1]
  47.  *  longjmp back to execute_fn_on_extra_stack [0]
  48.  * pointer to new stack is saved on m68k stack. m68k return address set
  49.  * to 0xF0FF00. m68k PC set to called function
  50.  * m68k function executes, stack is main
  51.  * m68k function returns to 0xF0FF00
  52.  * calltrap to m68k_mode_return
  53.  * do_stack_magic is called again
  54.  * current context is saved again with setjmp [0]
  55.  *  this time, transfer_control is _not_ done, instead a longjmp[1]
  56.  *  to the previously saved context
  57.  *   native code executes again on temp stack
  58.  *   native function returns to stack_stub
  59.  *  longjmp[0] back to old context
  60.  * back again!
  61.  *
  62.  * A bearded man enters the room, carrying a bowl of spaghetti.
  63.  */
  64.  
  65. /* This _shouldn't_ crash with a stack size of 4096, but it does...
  66.  * might be a bug */
  67. #ifndef EXTRA_STACK_SIZE
  68. #define EXTRA_STACK_SIZE 65536
  69. #endif
  70.  
  71. static void *extra_stack_list = NULL;
  72.  
  73. static void *get_extra_stack(void)
  74. {
  75.     void *s = extra_stack_list;
  76.     if (s)
  77.     extra_stack_list = *(void **)s;
  78.     if (!s)
  79.     s = xmalloc (EXTRA_STACK_SIZE);
  80.     return s;
  81. }
  82.  
  83. static void free_extra_stack (void *s)
  84. {
  85.     *(void **)s = extra_stack_list;
  86.     extra_stack_list = s;
  87. }
  88.  
  89. static void stack_stub (void *s, TrapFunction f, uae_u32 *retval)
  90. {
  91. #ifdef CAN_DO_STACK_MAGIC
  92.     /*printf("in stack_stub: %p %p %p %x\n", s, f, retval, (int)*retval);*/
  93.     *retval = f();
  94.     /*write_log ("returning from stack_stub\n");*/
  95.     longjmp(((jmp_buf *)s)[0], 1);
  96. #endif
  97. }
  98.  
  99. static void *current_extra_stack = NULL;
  100. static uaecptr m68k_calladdr;
  101.  
  102. static void do_stack_magic(TrapFunction f, void *s, int has_retval)
  103. {
  104. #ifdef CAN_DO_STACK_MAGIC
  105.     uaecptr a7;
  106.     jmp_buf *j = (jmp_buf *)s;
  107.     switch (setjmp(j[0])) {
  108.      case 0:
  109.     /* Returning directly */
  110.     current_extra_stack = s;
  111.     if (has_retval == -1) {
  112.         /*write_log ("finishing m68k mode return\n");*/
  113.         longjmp(j[1], 1);
  114.     }
  115.     /*write_log ("calling native function\n");*/
  116.     transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval);
  117.     /* not reached */
  118.     abort();
  119.  
  120.      case 1:
  121.     /*write_log ("native function complete\n");*/
  122.     /* Returning normally. */
  123.     if (stack_has_retval(s, EXTRA_STACK_SIZE))
  124.         m68k_dreg(regs, 0) = get_retval_from_stack(s, EXTRA_STACK_SIZE);
  125.     free_extra_stack(s);
  126.     break;
  127.  
  128.      case 2:
  129.     /* Returning to do a m68k call. We're now back on the main stack. */
  130.     a7 = m68k_areg(regs, 7) -= (sizeof (void *) + 7) & ~3;
  131.     /* Save stack to restore */
  132.     *((void **)get_real_address(a7 + 4)) = s;
  133.     /* Save special return address: this address contains a
  134.      * calltrap that will longjmp to the right stack. */
  135.     put_long (m68k_areg(regs, 7), 0xF0FF00);
  136.     m68k_setpc(m68k_calladdr);
  137.     /*write_log ("native function calls m68k\n");*/
  138.     break;
  139.     }
  140.     current_extra_stack = 0;
  141. #endif
  142. }
  143.  
  144. static uae_u32 execute_fn_on_extra_stack(TrapFunction f, int has_retval)
  145. {
  146.     uae_u32 retval = 0;
  147. #ifdef CAN_DO_STACK_MAGIC
  148.     void *s = get_extra_stack();
  149.     do_stack_magic (f, s, has_retval);
  150. #endif
  151.     return 0;
  152. }
  153.  
  154. static uae_u32 m68k_mode_return(void)
  155. {
  156. #ifdef CAN_DO_STACK_MAGIC
  157.     uaecptr a7 = m68k_areg(regs, 7);
  158.     void *s = *(void **)get_real_address(a7);
  159.     m68k_areg(regs, 7) += (sizeof (void *) + 3) & ~3;
  160.     /*write_log ("doing m68k mode return\n");*/
  161.     do_stack_magic (NULL, s, -1);
  162. #endif
  163.     return 0;
  164. }
  165.  
  166. static uae_u32 call_m68k(uaecptr addr, int saveregs)
  167. {
  168.     volatile uae_u32 retval = 0;
  169.     volatile int do_save = saveregs;
  170.     if (current_extra_stack == NULL)
  171.     abort();
  172. #ifdef CAN_DO_STACK_MAGIC
  173.     {
  174.     volatile struct regstruct saved_regs;
  175.     jmp_buf *j = (jmp_buf *)current_extra_stack;
  176.  
  177.     if (do_save)
  178.         saved_regs = regs;
  179.     m68k_calladdr = addr;
  180.     switch (setjmp(j[1])) {
  181.      case 0:
  182.         /*write_log ("doing call\n");*/
  183.         /* Returning directly: now switch to main stack and do the call */
  184.         longjmp (j[0], 2);
  185.      case 1:
  186.         /*write_log ("returning from call\n");*/
  187.         retval = m68k_dreg (regs, 0);
  188.         if (do_save)
  189.         regs = saved_regs;
  190.         /* Returning after the call. */
  191.         break;
  192.     }
  193.     }
  194. #endif
  195.     return retval;
  196. }
  197.  
  198. uae_u32 CallLib(uaecptr base, uae_s16 offset)
  199. {
  200.     int i;
  201.     uaecptr olda6 = m68k_areg(regs, 6);
  202.     uae_u32 retval;
  203. #if 0
  204.     for (i = 0; i < n_libpatches; i++) {
  205.     if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
  206.         return (*libpatches[i].functions[-offset/6])();
  207.     }
  208. #endif
  209.     m68k_areg(regs, 6) = base;
  210.     retval = call_m68k(base + offset, 1);
  211.     m68k_areg(regs, 6) = olda6;
  212.     return retval;
  213. }
  214.  
  215. /* Commonly used autoconfig strings */
  216.  
  217. uaecptr EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion;
  218. uaecptr EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36;
  219. uaecptr EXPANSION_bootcode, EXPANSION_nullfunc;
  220.  
  221. static int current_deviceno = 0;
  222.  
  223. int get_new_device(char **devname, uaecptr *devname_amiga)
  224. {
  225.     char buffer[80];
  226.  
  227.     sprintf(buffer,"UAE%d", current_deviceno);
  228.  
  229.     *devname_amiga = ds(*devname = my_strdup(buffer));
  230.     return current_deviceno++;
  231. }
  232.  
  233. /* ROM tag area memory access */
  234.  
  235. static uae_u8 rtarea[65536];
  236.  
  237. static uae_u32 rtarea_lget(uaecptr) REGPARAM;
  238. static uae_u32 rtarea_wget(uaecptr) REGPARAM;
  239. static uae_u32 rtarea_bget(uaecptr) REGPARAM;
  240. static void  rtarea_lput(uaecptr, uae_u32) REGPARAM;
  241. static void  rtarea_wput(uaecptr, uae_u32) REGPARAM;
  242. static void  rtarea_bput(uaecptr, uae_u32) REGPARAM;
  243. static uae_u8 *rtarea_xlate(uaecptr) REGPARAM;
  244.  
  245. addrbank rtarea_bank = {
  246.     rtarea_lget, rtarea_wget, rtarea_bget,
  247.     rtarea_lput, rtarea_wput, rtarea_bput,
  248.     rtarea_xlate, default_check
  249. };
  250.  
  251. uae_u8 REGPARAM2 *rtarea_xlate(uaecptr addr)
  252. {
  253.     addr &= 0xFFFF;
  254.     return rtarea + addr;
  255. }
  256.  
  257. uae_u32 REGPARAM2 rtarea_lget(uaecptr addr)
  258. {
  259.     addr &= 0xFFFF;
  260.     return (uae_u32)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2);
  261. }
  262.  
  263. uae_u32 REGPARAM2 rtarea_wget(uaecptr addr)
  264. {
  265.     addr &= 0xFFFF;
  266.     return (rtarea[addr]<<8) + rtarea[addr+1];
  267. }
  268.  
  269. uae_u32 REGPARAM2 rtarea_bget(uaecptr addr)
  270. {
  271.     uae_u16 data;
  272.     addr &= 0xFFFF;
  273.     return rtarea[addr];
  274. }
  275.  
  276. void REGPARAM2 rtarea_lput(uaecptr addr, uae_u32 value) { }
  277. void REGPARAM2 rtarea_wput(uaecptr addr, uae_u32 value) { }
  278. void REGPARAM2 rtarea_bput(uaecptr addr, uae_u32 value) { }
  279.  
  280. static int trace_traps = 1;
  281.  
  282. void REGPARAM2 call_calltrap(int func)
  283. {
  284.     uae_u32 retval = 0;
  285.     int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0;
  286.     int implicit_rts = (trapmode[func] & TRAPFLAG_DORET) != 0;
  287.  
  288.     if (*trapstr[func] != 0 && trace_traps) {
  289.     sprintf (warning_buffer, "TRAP: %s\n", trapstr[func]);
  290.     write_log (warning_buffer);
  291.     }
  292.  
  293.     /* For monitoring only? */
  294.     if (traps[func] == NULL) {
  295.     m68k_setpc(trapoldfunc[func]);
  296.     return;
  297.     }
  298.  
  299.     if (func < max_trap) {
  300.     if (trapmode[func] & TRAPFLAG_EXTRA_STACK) {
  301.         execute_fn_on_extra_stack(traps[func], has_retval);
  302.         return;
  303.     }
  304.     retval = (*traps[func])();
  305.     } else {
  306.     fprintf(stderr, "illegal emulator trap\n");
  307.     }
  308.     if (has_retval)
  309.     m68k_dreg(regs, 0) = retval;
  310.     if (implicit_rts)
  311.     m68k_do_rts();
  312. }
  313.  
  314. /* @$%&§ compiler bugs */
  315. static volatile int four = 4;
  316.  
  317. uaecptr libemu_InstallFunctionFlags(TrapFunction f, uaecptr libbase, int offset,
  318.                     int flags, const char *tracename)
  319. {
  320.     int i;
  321.     uaecptr retval;
  322.     uaecptr execbase = get_long(four);
  323.     int trnum;
  324.     uaecptr addr = here();
  325.     calltrap(trnum = deftrap2(f, flags, tracename));
  326.     dw(RTS);
  327.  
  328.     m68k_areg(regs, 1) = libbase;
  329.     m68k_areg(regs, 0) = offset;
  330.     m68k_dreg(regs, 0) = addr;
  331.     retval = CallLib(execbase, -420);
  332.  
  333.     trapoldfunc[trnum] = retval;
  334. #if 0
  335.     for (i = 0; i < n_libpatches; i++) {
  336.     if (libpatches[i].libbase == libbase)
  337.         break;
  338.     }
  339.     if (i == n_libpatches) {
  340.     int j;
  341.     libpatches[i].libbase = libbase;
  342.     for (j = 0; j < 300; j++)
  343.         libpatches[i].functions[j] = NULL;
  344.     n_libpatches++;
  345.     }
  346.     libpatches[i].functions[-offset/6] = f;
  347. #endif
  348.     return retval;
  349. }
  350.  
  351. /* some quick & dirty code to fill in the rt area and save me a lot of
  352.  * scratch paper
  353.  */
  354.  
  355. static int rt_addr = 0;
  356. static int rt_straddr = 0xFF00 - 2;
  357.  
  358. uae_u32 addr(int ptr)
  359. {
  360.     return (uae_u32)ptr + 0x00F00000;
  361. }
  362.  
  363. void db(uae_u8 data)
  364. {
  365.     rtarea[rt_addr++] = data;
  366. }
  367.  
  368. void dw(uae_u16 data)
  369. {
  370.     rtarea[rt_addr++] = data >> 8;
  371.     rtarea[rt_addr++] = data;
  372. }
  373.  
  374. void dl(uae_u32 data)
  375. {
  376.     rtarea[rt_addr++] = data >> 24;
  377.     rtarea[rt_addr++] = data >> 16;
  378.     rtarea[rt_addr++] = data >> 8;
  379.     rtarea[rt_addr++] = data;
  380. }
  381.  
  382. /* store strings starting at the end of the rt area and working
  383.  * backward.  store pointer at current address
  384.  */
  385.  
  386. uae_u32 ds(char *str)
  387. {
  388.     int len = strlen(str) + 1;
  389.  
  390.     rt_straddr -= len;
  391.     strcpy((char *)rtarea + rt_straddr, str);
  392.  
  393.     return addr(rt_straddr);
  394. }
  395.  
  396. void calltrap(uae_u32 n)
  397. {
  398.     dw(0xA000 + n);
  399. }
  400.  
  401. void org(uae_u32 a)
  402. {
  403.     rt_addr = a - 0x00F00000;
  404. }
  405.  
  406. uae_u32 here(void)
  407. {
  408.     return addr(rt_addr);
  409. }
  410.  
  411. int deftrap2(TrapFunction func, int mode, const char *str)
  412. {
  413.     int num = max_trap++;
  414.     traps[num] = func;
  415.     trapstr[num] = str;
  416.     trapmode[num] = mode;
  417.     return num;
  418. }
  419.  
  420. int deftrap(TrapFunction func)
  421. {
  422.     return deftrap2(func, 0, "");
  423. }
  424.  
  425. void align(int b)
  426. {
  427.     rt_addr = (rt_addr + (b-1)) & ~(b-1);
  428. }
  429.  
  430. static uae_u32 nullfunc(void)
  431. {
  432.     fprintf(stderr, "Null function called\n");
  433.     return 0;
  434. }
  435.  
  436. static uae_u32 getchipmemsize (void)
  437. {
  438.     return chipmem_size;
  439. }
  440.  
  441. void rtarea_init()
  442. {
  443.     uae_u32 a;
  444.     char uaever[100];
  445.     sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10);
  446.  
  447.     EXPANSION_uaeversion = ds(uaever);
  448.     EXPANSION_explibname = ds("expansion.library");
  449.     EXPANSION_doslibname = ds("dos.library");
  450.     EXPANSION_uaedevname = ds("uae.device");
  451.  
  452.     deftrap(NULL); /* Generic emulator trap */
  453.     lasttrap = 0;
  454.  
  455.     EXPANSION_nullfunc = here();
  456.     calltrap(deftrap(nullfunc));
  457.     dw(RTS);
  458.  
  459.     a = here();
  460.     /* Standard "return from 68k mode" trap */
  461.     org(0xF0FF00);
  462.     calltrap (deftrap2 (m68k_mode_return, TRAPFLAG_NO_RETVAL, ""));
  463.  
  464.     org (0xF0FF80);
  465.     calltrap (deftrap2 (getchipmemsize, TRAPFLAG_DORET, ""));
  466.     org(a);
  467.  
  468.     filesys_install_code ();
  469. }
  470.  
  471. volatile int uae_int_requested = 0;
  472.  
  473. void set_uae_int_flag (void)
  474. {
  475.     rtarea[0xFFFB] = uae_int_requested;
  476. }
  477.  
  478. void rtarea_setup(void)
  479. {
  480. }
  481.